﻿using System;
using System.IO; 
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace T3K.SketchEditor.Core {
    public class FileTemplate {

        private Dictionary<string, string> _options;
        private string _codeTemplate;
        private string _templateName;
        private string _fileName;

        #region Properties

        public string TemplateName {
            get { return _templateName; }
        }

        public string FileName {
            get { return _fileName; }
        }

        public string Icon {
            get {
                string icon = this["Icon"];
                return (icon != null) ? icon : string.Empty;
            }
        }

        public string Extention {
            get {
                string ext = this["Extention"];
                return (ext != null) ? "." + ext : string.Empty;
            }
        }

        public string Name {
            get {
                string name = this["Name"];
                return (name != null) ? name : string.Empty;
            }
        }

        public string Description {
            get {
                string value = this["Description"];
                return (value != null) ? value : string.Empty;
            }
        }

        public bool Public {
            get {
                string value = this["Public"];
                return (value != null && value.ToLower() == "yes") ? true : false;
            }
        }

        public string this[string key] {
            get {
                if (_options.ContainsKey(key.ToUpper()))
                    return _options[key.ToUpper()];
                else
                    return null;
            }
        }

        public string CodeTemplate {
            get { return _codeTemplate; }
        }
        #endregion

        public string GetCode(Dictionary<string, object> vars) {
            return Expand(_codeTemplate, vars);
        }

        private static Regex reArgs = new Regex("\\$\\(([a-zA-Z0-9_]+)\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private string Expand(string code, Dictionary<string, object> vars) {
            if (reArgs.IsMatch(code)) {
                code = reArgs.Replace(code, new MatchEvaluator(
                    delegate(Match match) {
                        if (match.Groups.Count > 0) {
                            string key = match.Groups[1].Value;
                            if (vars.ContainsKey(key))
                                return vars[key].ToString();
                            else
                                return string.Empty;
                        } else
                            return match.Value;
                    }
                ));
            }

            return code;
        }

        private string ReplaceArgs_A(Match match) {
            if (match.Groups.Count > 0) {
                string key = match.Groups[1].Value;
                return this[key];
            } else
                return match.Value;
        }

        private FileTemplate(FileInfo templateFile) {

            _options = new Dictionary<string, string>();

            if (templateFile.Exists) {

                _fileName = templateFile.FullName;
                _templateName = templateFile.Name.Substring(0, templateFile.Name.Length - templateFile.Extension.Length);

                StreamReader sr = new StreamReader(templateFile.OpenRead());
                string line;
                int mode = 0;
                StringBuilder code = new StringBuilder();

                while ((line = sr.ReadLine()) != null) {
                    if (mode == 0 && (line.IndexOf('=') > -1)) {
                        line = line.Trim();
                        string[] tokens = line.Split(new char[] { '=' }, 2, StringSplitOptions.None);
                        if (tokens.Length == 2) {
                            string key = tokens[0].Trim().ToUpper();
                            string value = tokens[1].Trim();
                            if (!_options.ContainsKey(key))
                                _options.Add(key, value);
                            else
                                _options[key] = value;
                        }
                    } else if (mode == 0 && line.Trim().ToUpper() == "BEGIN:") {
                        mode = 1;
                    } else if (mode == 1) {
                        code.AppendLine(line);
                    }
                }

                _codeTemplate = code.ToString();
            } else
                throw new ArgumentException(string.Format("{0} file doe not exist", templateFile.Name));

        }

        private static List<FileTemplate> _templates = null;
        private static object _templatesLocker = new object();

        public static List<FileTemplate> GetTemplates() {
            if (_templates == null) {
                DirectoryInfo dInfo = new DirectoryInfo("Templates");
                if (dInfo.Exists) {
                    lock (_templatesLocker) {
                        if (_templates == null)
                            _templates = GetTemplates(dInfo);
                    }
                } else {
                    _templates = new List<FileTemplate>(); 
                }
            }
            return _templates;
        }

        private static List<FileTemplate> GetTemplates(DirectoryInfo dInfo) {
            List<FileTemplate> templates = new List<FileTemplate>();

            foreach (FileInfo fInfo in dInfo.GetFiles()) {
                if (fInfo.Extension.ToLower() == ".tmpl")
                    templates.Add(new FileTemplate(fInfo));

            }

            return templates;
        }


    }
}
